package com.jf.cloud.service.sysmanager.common.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.Date;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * Excel工具类
 * 
 * @author 程伟平 创建时间：2012-02-23 10:30:50
 */

public final class XSSFExcelUtil {

	/**
	 * 读取Excel模板文件
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param inputStream 输入流
	 * @return Excel工作簿
	 * @throws IOException
	 */
	public static XSSFWorkbook read(InputStream inputStream) throws IOException {
		return new XSSFWorkbook(inputStream);
	}

	/**
	 * 设置Excel工作表单元格的值。
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param rowIndex 行索引
	 * @param columnIndex 列索引
	 * @param value 値
	 */
	public static void setCellValue(XSSFSheet sheet, int rowIndex, int columnIndex, Object value) {
		XSSFRow row = sheet.getRow(rowIndex);

		XSSFCell cell = row.getCell(columnIndex);
		setCellValue(cell, value);
	}

	/**
	 * 设置Excel工作表单元格的值——附带单元格样式。
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param rowIndex 行索引
	 * @param columnIndex 列索引
	 * @param value 値
	 * @param cellStyle 单元格样式
	 */
	public static void setCellValue(XSSFSheet sheet, int rowIndex, int columnIndex, Object value, XSSFCellStyle cellStyle) {
		XSSFRow row = sheet.getRow(rowIndex);

		XSSFCell cell = row.getCell(columnIndex);
		setCellValue(cell, value);
		cell.setCellStyle(cellStyle);
	}

	/**
	 * 根据类型设置Excel工作表单元格的值。
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param cell 单元格
	 * @param value 值
	 */
	private static void setCellValue(XSSFCell cell, Object value) {
		if (value != null) {
			// 字符型
			if (value instanceof String) {
				String strValue = (String) value;
				cell.setCellValue(new XSSFRichTextString(strValue));
			}
			// 整型
			else if (value instanceof Integer) {
				Integer longValue = (Integer) value;
				cell.setCellValue(longValue);
			}
			// 长整型
			else if (value instanceof Long) {
				Long longValue = (Long) value;
				cell.setCellValue(longValue);
			}
			// 双精度实数型
			else if (value instanceof Double) {
				Double doubleValue = (Double) value;
				cell.setCellValue(doubleValue);
			}
			// 日期型
			else if (value instanceof Calendar) {
				Calendar calendarValue = (Calendar) value;
				cell.setCellValue(calendarValue);
			}
			// 日期型
			else if (value instanceof Date) {
				Date dateValue = (Date) value;
				cell.setCellValue(dateValue);
			}
		}
	}

	/**
	 * 获取Excel工作表单元格样式。
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param rowIndex 行索引
	 * @param columnIndex 列索引
	 * @return 单元格样式
	 */
	public static XSSFCellStyle getCellStyle(XSSFSheet sheet, int rowIndex, int columnIndex) {
		XSSFRow row = sheet.getRow(rowIndex);

		XSSFCell cell = row.getCell(columnIndex);
		return cell.getCellStyle();
	}

	/**
	 * 设置Excel工作表单元格样式。
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param rowIndex 行索引
	 * @param columnIndex 列索引
	 * @param cellStyle 单元格样式
	 */
	public static void setCellStyle(XSSFSheet sheet, int rowIndex, int columnIndex, XSSFCellStyle cellStyle) {
		XSSFRow row = sheet.getRow(rowIndex);

		XSSFCell cell = row.getCell(columnIndex);
		cell.setCellStyle(cellStyle);
	}

	/**
	 * 获取Excel工作表列宽度
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param columnIndex 列索引
	 * @return 列宽度
	 */
	public static int getColumnWidth(XSSFSheet sheet, int columnIndex) {
		return sheet.getColumnWidth(columnIndex);
	}

	/**
	 * 设置Excel工作表列宽度
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param columnIndex 列索引
	 * @param width 列宽度
	 */
	public static void setColumnWidth(XSSFSheet sheet, int columnIndex, int width) {
		sheet.setColumnWidth(columnIndex, width);
	}

	/**
	 * 合并Excel工作表单元格
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param firstRow 开始行
	 * @param lastRow 结束行
	 * @param firstCol 开始列
	 * @param lastCol 结束列
	 */
	public static void addMergedRegion(XSSFSheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
		sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
	}

	/**
	 * 获取Excel工作表单元格的值
	 * 
	 * @author 程伟平 2012-03-13
	 * @param row Excel工作表行
	 * @param columnIndex 列索引
	 * @return 单元格的值
	 */
	public static String getCellValue(XSSFRow row, int columnIndex) {
		XSSFCell cell = row.getCell(columnIndex);
		// 数字
		if (XSSFCell.CELL_TYPE_NUMERIC == cell.getCellType()) {
			return String.valueOf(cell.getNumericCellValue());
		} else {
			return cell.getStringCellValue();
		}
	}

	/**
	 * 获取Excel工作表单元格的值
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param rowIndex 行索引
	 * @param columnIndex 列索引
	 * @return 单元格的值
	 */
	public static String getCellValue(XSSFSheet sheet, int rowIndex, int columnIndex) {
		XSSFRow row = sheet.getRow(rowIndex);
		XSSFCell cell = row.getCell(columnIndex);
		// 数字
		if (HSSFCell.CELL_TYPE_NUMERIC == cell.getCellType()) {
			return String.valueOf(cell.getNumericCellValue());
		} else {
			return cell.getStringCellValue();
		}
	}

	/**
	 * 获取Excel工作表单元格的值
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param rowIndex 行索引
	 * @param columnIndex 列索引
	 * @param textFlag 是否强制文本值
	 * @return 单元格的值
	 */
	public static String getCellValue(XSSFSheet sheet, int rowIndex, int columnIndex, boolean textFlag) {
		XSSFRow row = sheet.getRow(rowIndex);
		XSSFCell cell = row.getCell(columnIndex);
		// 强制文本值
		if(textFlag) {
			cell.setCellType(XSSFCell.CELL_TYPE_STRING);
		}
		// 数字
		if (XSSFCell.CELL_TYPE_NUMERIC == cell.getCellType()) {
			return String.valueOf(cell.getNumericCellValue());
		}
		return cell.getStringCellValue();
	}

	/**
	 * 在Excel工作表的开始行后插入N行，格式与开始行相同。
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param starRowIndex 开始行索引
	 * @param n 插入的行数
	 */
	public static void insertRow(XSSFSheet sheet, int starRowIndex, int n) {

		XSSFRow sourceRow = null;
		XSSFRow targetRow = null;
		XSSFCell sourceCell = null;
		XSSFCell targetCell = null;

		sheet.shiftRows(starRowIndex + 1, sheet.getLastRowNum(), n, true, false);

		for (int i = 0; i < n; i++) {
			sourceRow = sheet.getRow(starRowIndex + i);
			targetRow = sheet.createRow(starRowIndex + i + 1);

			targetRow.setHeight(sourceRow.getHeight());

			for (int k = sourceRow.getFirstCellNum(); k < sourceRow.getLastCellNum(); k++) {

				sourceCell = sourceRow.getCell(k);
				targetCell = targetRow.createCell(k);

				for (int m = 0; m < sheet.getNumMergedRegions(); m++) {
					CellRangeAddress region = sheet.getMergedRegion(m);
					int firstRow = region.getFirstRow();
					int lastRow = region.getLastRow();
					int firstCol = region.getFirstColumn();
					int lastCol = region.getLastColumn();

					if (firstRow == sourceRow.getRowNum() && firstCol == sourceCell.getColumnIndex()) {
						firstRow = lastRow = targetRow.getRowNum();
						addMergedRegion(sheet, firstRow, lastRow, firstCol, lastCol);
						break;
					}
				}

				if (sourceCell != null) {
					targetCell.setCellStyle(sourceCell.getCellStyle());
					targetCell.setCellType(sourceCell.getCellType());
				}
			}
		}
	}

	/**
	 * 删除行
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param rowIndex 行索引
	 */
	public static void removeRow(XSSFSheet sheet, int rowIndex) {
		sheet.removeRow(sheet.getRow(rowIndex));
	}

	/**
	 * 删除列
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param sheet Excel工作表
	 * @param rowIndex 行索引
	 * @param columnIndex 列索引
	 */
	public static void removeCol(XSSFSheet sheet, int rowIndex, int columnIndex) {
		XSSFCell cell = sheet.getRow(rowIndex).getCell(columnIndex);
		sheet.getRow(rowIndex).removeCell(cell);
	}

	/**
	 * 输出Excel文件
	 * 
	 * @author 程伟平 创建时间：2012-02-23 10:30:50
	 * @param workbook Excel工作簿
	 * @param outputStream 输出流
	 * @throws IOException
	 */
	public static void write(XSSFWorkbook workbook, OutputStream outputStream) throws IOException {
		workbook.write(outputStream);
	}

}
